#include "funcProcStructIng.h"

void FuncProcStructIng::liberar_datos(){
	std::vector<TipoDato *>::iterator it = datos.begin();
	
	while(it != datos.end() ){
		delete (*it);
		++it;
	}
	
	this->datos.clear();
}

FuncProcStructIng::~FuncProcStructIng(){
	liberar_datos();
}

unsigned int FuncProcStructIng::operator() (const std::string &expr, TipoStruct* reg_modelo, unsigned int pos){
	
	bool cargado = false; //Indica si se cargo o no el tipo compuesto
	
	//Obtengo los datos atomicos dentro del struct
	liberar_datos();
	this->datos = Parser::obtener_datos_atomicos(expr);
	
	//Proceso el dato mientras no se haya cargado y haya campos en el reg con quienes comparar
	while ( (!cargado) && (pos < reg_modelo->get_tamanio()) ) {
		 //Campo del registro a tratar
		TipoDato* campo = &((*reg_modelo)[pos]);
		//Si el campo es una estructura lo proceso como struct (estructura monovalente y obligatoria)
		//Si hay un error cargandola, el proc estructura arroja una excep q se propaga para arriba.
		if (campo->get_codigo_tipo() == STRUCT) {
			procesar_estructura((TipoStruct*) campo);
			cargado = true;
		} else { //sino, si el campo es polivalente (coleccion), lo proceso
				if (campo->get_codigo_tipo() == COLECCION){
					try {
						//Intento cargar la coleccion, si no puedo cargarla cacheo la excep
						procesar_coleccion((TipoColec*) campo);
						//Si cargo pongo cargado en true
						cargado = true;
					} catch (ExcepSintaxisParser &e) {
						pos++;	
					} catch (ExcepErrorTipos &e) {
						pos++;	
					}
				} else //sino hay error de parseo
					throw ExcepSintaxisParser ("Error - Sintaxis de datos de entrada incorrecta.");
		}
	}
	if (!cargado)
		throw ExcepSintaxisParser("Error - Sintaxis de datos de entrada incorrecta.");
	return pos + 1;
}

void FuncProcStructIng::procesar_estructura(TipoStruct* estructura){
	
	//Si es un struct cargo todos los datos en un struct auxiliar y desp lo asigno
	TipoStruct struct_aux( estructura->es_obligatorio() );
	std::vector<TipoDato*>::iterator it = datos.begin();
	while (it != datos.end()) {
		TipoDato* aux = (*it);
		struct_aux.add_dato(*aux);
		it++;
	}
	//ASIGNACION, si falla tira una excepcion
	*((TipoDato*)estructura) = struct_aux;
}
	
void FuncProcStructIng::procesar_coleccion(TipoColec* colec){
	//Pido el tipo base y trabajo con eso
	TipoDato* tipo_modelo = colec->get_tipo_modelo();
	std::vector<TipoDato*>::iterator it = datos.begin();
	//Obtengo el tamanio del tipo modelo
	unsigned int size = tipo_modelo->get_tamanio();
	unsigned int cont = 0;
	//Voy cargando un struct aux y lo trato de meter en la coleccion
	while (it != datos.end()) {
		TipoStruct struct_aux(colec->es_obligatorio());
		while ((cont < size) && (it != datos.end())) {
				TipoDato* aux = (*it);
				struct_aux.add_dato(*aux);
				cont++;
				it++;
		}
		//AGREGO EL DATO, si devuelve false hubo error de sintaxis asi q arrojo excep
		if (!colec->add_dato(struct_aux)) {
			colec->clear();
			delete(tipo_modelo);
			throw ExcepSintaxisParser ("Error - Sintaxis de datos de entrada incorrecta.");
		}
		cont = 0;
	}
	delete(tipo_modelo);
}
